﻿using System;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using NUnit.Framework.SyntaxHelpers;
using Yaml.Presentation.Parsing;
using Yaml.Presentation.Tokens;

namespace Yaml.Tests.Presentation.ScannerTests {
    [TestFixture]
    public class Flows {
        [Test]
        public void SequenceStart() {
            Scanner s = Helper.CreateScanner("[");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={1:0,1} end={1:0,1}>"));
        }
        [Test]
        public void EmptySequence() {
            Scanner s = Helper.CreateScanner("[]");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceEndToken flowDepth='0' start={1:0,1} end={2:0,2}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={2:0,2} end={2:0,2}>"));
        }
        [Test]
        public void NestedSequence() {
            Scanner s = Helper.CreateScanner("[\n[]\n]");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceStartToken flowDepth='2' start={2:1,0} end={3:1,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceEndToken flowDepth='1' start={3:1,1} end={4:1,2}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceEndToken flowDepth='0' start={5:2,0} end={6:2,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={6:2,1} end={6:2,1}>"));
        }

        [Test]
        public void MappingStart() {
            Scanner s = Helper.CreateScanner("{");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            Assert.That(s.State.FlowDepth, Is.EqualTo(0));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={1:0,1} end={1:0,1}>"));
        }
        [Test]
        public void EmptyMapping() {
            Scanner s = Helper.CreateScanner("{}");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingEndToken flowDepth='0' start={1:0,1} end={2:0,2}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={2:0,2} end={2:0,2}>"));
        }
        [Test]
        public void NestedMapping() {
            Scanner s = Helper.CreateScanner("{\n{}\n}");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingStartToken flowDepth='2' start={2:1,0} end={3:1,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingEndToken flowDepth='1' start={3:1,1} end={4:1,2}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowMappingEndToken flowDepth='0' start={5:2,0} end={6:2,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={6:2,1} end={6:2,1}>"));
        }

        [Test]
        public void SequencesAndMappings() {
            Scanner s = Helper.CreateScanner("%YAML 1.1\n%TAG ! tag://mydomain.com\n[ { } # Mapping inside sequence\n] {\n [   ] #Sequence inside mapping\n}");
            Token t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(StreamStartToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(YamlDirectiveToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(TagDirectiveToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowSequenceStartToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowMappingStartToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowMappingEndToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowSequenceEndToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowMappingStartToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowSequenceStartToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowSequenceEndToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(FlowMappingEndToken)));
            t = s.GetToken();
            Assert.That(t, Is.InstanceOfType(typeof(StreamEndToken)));
        }

        [Test]
        public void FlowEntry() {
            Scanner s = Helper.CreateScanner("[ , ]");
            Token t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamStartToken encoding='utf-8' start={0:0,0} end={0:0,0}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceStartToken flowDepth='1' start={0:0,0} end={1:0,1}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowEntryToken flowDepth='1' start={2:0,2} end={3:0,3}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<FlowSequenceEndToken flowDepth='0' start={4:0,4} end={5:0,5}>"));
            t = s.GetToken();
            Assert.That(t.ToString(), Is.EqualTo("#<StreamEndToken start={5:0,5} end={5:0,5}>"));
        }
    }
}
